package com.ap.core.jbehave.confirmpayment;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

import java.math.BigDecimal;

import org.hamcrest.CoreMatchers;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import com.ap.core.cxf.jaxb.common.APCORE1FaultDetailsType;
import com.ap.core.cxf.jaxb.managepayment.ConfirmPayment1Request;
import com.ap.core.cxf.jaxb.managepayment.ConfirmPayment1Response;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Request;
import com.ap.core.cxf.jaxb.managepayment.RetrieveRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Request;
import com.ap.core.cxf.jaxb.managertp.SubmitRTP1Response;
import com.ap.core.cxf.jaxb.managertp.SubmitRTPMessageType;
import com.ap.core.cxf.jaxb.msghdr.MessageType;
import com.ap.core.cxf.jaxb.rtp.TransactionCheckOutType;
import com.ap.core.jbehave.BaseTransitionRTPSteps;
import com.ap.core.jbehave.StoryContext;
import com.ap.core.util.JaxbUtil;
import com.ap.core.util.Nullable;
import com.ap.core.util.TypedKey;
import com.core.ap.wsdl.managepaymentservice_1.ConfirmPayment1Fault;
import com.core.ap.wsdl.managepaymentservice_1.ManagePayment1PortType;
import com.core.ap.wsdl.managepaymentservice_1.RetrieveRTP1Fault;
import com.core.ap.wsdl.managertpservice_1.ManageRTP1PortType;
import com.core.ap.wsdl.managertpservice_1.SubmitRTP1Fault;

public class ConfirmPaymentFaultSteps extends BaseTransitionRTPSteps {

	private static final TypedKey<Nullable<SubmitRTP1Response>> SUBMIT_RTP_RESPONSE  = new TypedKey<>("SubmitRTPResponseType");
	private static final TypedKey<Nullable<RetrieveRTP1Response>> RETRIEVE_RTP_RESPONSE  = new TypedKey<>("RetreiveRTPResponseType");
	private static final TypedKey<Nullable<ConfirmPayment1Response>> CONFIRM_PAYMENT_RESPONSE  = new TypedKey<>("ConfirmPaymentResponseType");
	
	private SubmitRTP1Request submitRTPRequest;
	private RetrieveRTP1Request retrieveRTPRequest;
	private ConfirmPayment1Request confirmPayment1Request;
	private  SubmitRTP1Response responseRTPType;
	private RetrieveRTP1Response retrieveRTPResponse;
	
	public ConfirmPaymentFaultSteps(StoryContext storyContext) {
        super(storyContext);
	}

	@Given("the OSB has submitted a structurally valid SUBMITRTPFORMOB request to APCore")
	public void giveBankCompletedMComPayment() throws Exception {
        processRequiredMessagesForConfirmPaymentMessage(SubmitRTPMessageType.SUBMITRTPFORMOB);
	}


    @When("APCore receives the structurally valid CONFIRMPAYMENT request from OSB")
	public void whenAPReceivesPaymentConfirmation() throws Exception {
        processConfirmPaymentMessage();

	}




  

  


    private void processRequiredMessagesForConfirmPaymentMessage(SubmitRTPMessageType messageType) throws SubmitRTP1Fault, RetrieveRTP1Fault {
        final ManageRTP1PortType singnedPort = factory.getBean(ManageRTP1PortType.class);
        submitRTPRequest = createSubmitRTPRequest(messageType);
        submitRTPRequest.getRTPSenderInfo().getDistributorInfo().setDistributorId("000001");
        submitRTPRequest.getRTPSenderInfo().getDetailMerchantInfo().getMerchantInfo().setMerchantId("000001");

        LOG.info("Given -  the OSB has submitted a structurally valid SUBMITRTPFORMOB request to APCore");
        JaxbUtil.newInstance().javaToXML(SubmitRTP1Request.class, submitRTPRequest);

        responseRTPType = singnedPort.submitRTP1(submitRTPRequest);

        LOG.info("AND - APCore successfully responded and stored the request with RTPSUBMITTED");
        JaxbUtil.newInstance().javaToXML(SubmitRTP1Response.class, responseRTPType);

       // storyContext.put(SUBMIT_RTP_RESPONSE, Nullable.nullable(responseRTPType));

        final ManagePayment1PortType managePaymentSignedPort = factory.getBean(ManagePayment1PortType.class);
        retrieveRTPRequest = createRetrieveRTPRequest();
        
        if(SubmitRTPMessageType.SUBMITRTPFORMOB.equals(messageType)){
        	retrieveRTPRequest.getRequestInfo().setApTransactionId(responseRTPType.getResponseInfo().getApTransactionId());
        	retrieveRTPRequest.getRequestInfo().setApTRId(responseRTPType.getResponseInfo().getApTRId());
        	retrieveRTPRequest.getRequestInfo().setBRN(null);
        }else{
        	retrieveRTPRequest.getRequestInfo().setApTransactionId(null);
        	retrieveRTPRequest.getRequestInfo().setApTRId(null);
        	retrieveRTPRequest.getRequestInfo().setBRN(responseRTPType.getResponseInfo().getBRN());
        }
      
        
        retrieveRTPRequest.getRequestInfo().setFIId("000001");
        retrieveRTPRequest.getRequestInfo().setFIConsumerId("ntwdcon1");

        LOG.info("AND - OSB successfully submitted a structurally valid RetrieveRTP request to APCore");

        JaxbUtil.newInstance().javaToXML(RetrieveRTP1Request.class, retrieveRTPRequest);
        retrieveRTPResponse = managePaymentSignedPort.retrieveRTP1(retrieveRTPRequest);

        LOG.info("AND - APCore successfully responded and stored the request with RTPRETRIEVED");
        JaxbUtil.newInstance().javaToXML(RetrieveRTP1Response.class, retrieveRTPResponse);

    }

    private void processConfirmPaymentMessage() throws ConfirmPayment1Fault {
        final ManagePayment1PortType managePayment1PortType = factory.getBean(ManagePayment1PortType.class);



        confirmPayment1Request = createConfirmPayment1Request(MessageType.CONFIRMPAYMENT, TransactionCheckOutType.NRMLCHK, submitRTPRequest.getDelivery().getDeliveryType());

        confirmPayment1Request.getPaymtDetails().setApTransactionId(retrieveRTPResponse.getRTPIdentifier().getApTransactionId());
        confirmPayment1Request.getPaymtDetails().setApTRId(retrieveRTPResponse.getRTPIdentifier().getApTRId());

        confirmPayment1Request.getConsumerAcct().setFIId(retrieveRTPResponse.getConsumerInfo().getFIId());
        //confirmPayment1Request.getPaymtDetails().getPaymentStatusInfo().setTotalPaymentReqAmount(retrieveRTPResponse.value().getRTPSummary().getPaymtAmtInfo().getTotalPaymentReqAmount());
        
        confirmPayment1Request.getPaymtDetails().getPaymentStatusInfo().setTotalPaymentReqAmount(new BigDecimal(1234567));
        
        JaxbUtil.newInstance().javaToXML(ConfirmPayment1Request.class, confirmPayment1Request);
        LOG.info("When -  APCore receives the structurally valid CONFIRMPAYMENT request from OSB");
        
        try {
        	managePayment1PortType.confirmPayment1(confirmPayment1Request);
		} catch (ConfirmPayment1Fault fault) {
			TypedKey<ConfirmPayment1Fault> FAULT = new TypedKey<ConfirmPayment1Fault>("AMOUNT");
			storyContext.put(FAULT, fault);
		}

    }
    
    @Then("APCore sends appropriate Fault message to OSB")
	public void thenAPServiceWillRespondwithSoapFault() {
		for (TypedKey<ConfirmPayment1Fault> key : storyContext.keySet()) {
			APCORE1FaultDetailsType fault = storyContext.get(key).getFaultInfo();
			StringBuilder stringBuilder = new StringBuilder(150);
	    	stringBuilder.append("\n FaultString:"+fault.toString());
	    	stringBuilder.append(" FaultId:"+fault.getFaultid());
	    	stringBuilder.append("\n"+" Errorcode:"+fault.getErrorcode());
	        stringBuilder.append( " ErrorMessage:"+fault.getErrormessage());
	        stringBuilder.append("\n"+" InternalErrorCode:"+fault.getInternalcode());
	        stringBuilder.append(" InternalErrorMessage:"+fault.getInternalmessage());
	        String message = stringBuilder.toString();
			LOG.info("\n\nFault Error Details for "	+key+ " :"+ message+"\n");
			JaxbUtil.newInstance().javaToXML(APCORE1FaultDetailsType.class, fault);

			assertThat("Fault Id is not as expected", false, CoreMatchers.is(equalTo(fault.getFaultid() == null)));
		    assertThat("Error code is not as expected",	false,	CoreMatchers.is(equalTo(fault.getErrorcode() == null)));
		    assertThat("Error Message is not as expected", false, CoreMatchers.is(equalTo(fault.getErrormessage() == null)));
		    assertThat("Internal Code is not as expected", false, CoreMatchers.is(equalTo(fault.getInternalcode() == null)));
		    assertThat("Internal Message is not as expected", false, CoreMatchers.is(equalTo(fault.getInternalmessage() == null)));
		}
	}
	
}
